/*
 * user.c
 *
 *  Created on: Dec 6, 2013
 *      Author: Ahmed
 */

/* This file contains all the routines that handle the user interface being
 * push buttons or LCD updates
*/

#include "stm32f10x.h"
#include "buttons.h"
#include "main.h"
#include "panes.h"
#include "datetime.h"
#include "nokia-5110.h"
#include "spieeprom.h"
#include "storage.h"
#include "serial.h"

#define	DAY		0
#define	MONTH	1
#define	YEAR	2
#define	HOUR	3
#define	MINUTE	4
#define	INIT	0xFF
#define	MAX_DAYS_FREQ	7		// Maximum number of days as frequency of taking samples
#define	MAX_HOURS_FREQ	24		// Maximum number of hours as frequency of taking samples
#define	FREQ_VALUE	0
#define	FREQ_UNIT	1

void updateButtonState(void);
void updateDisplay(uint8_t);
void manageDateTimeInput(uint8_t, uint8_t, epochTimeTypeDef *, uint8_t);
void manageLogFreqPane(uint8_t);
void manageLCDOffPane(uint8_t);
void manageStatusPane(void);
void manageSerialPane(void);

uint8_t paneNum = 0;
uint8_t prevPaneNum = 0;
uint8_t selected_date_time_field = DAY;
uint8_t	freq_selection = FREQ_VALUE;
uint32_t RTC_Alarm_Count;
										// "Xx/Xx/Xx Xx:Xx"
										//  01234567890123
uint8_t	date_time_selection[5]={0,3,6,9,12};	//stores the LCD column# for displaying the different time stamp fields.
												// The LCD row# is passed dynamically to te function that displays
char *freq_unit_abrv[] = {"mins","hours","days"};
							// button idle, pressed down, released up, short press, long press
uint8_t buttonState = BT_UP;
uint8_t processButtonState = BT_DONE;
epochTimeTypeDef date_time, date_time2;		//stores current date and time, or start and stop date and time
uint8_t	tempFreqVal, tempFreqType;

extern uint16_t ISR_type;		// stores the ISR type that woke up the processor from STOP
extern pane	panels[];
extern userSettingsDef userSettings;		// store all user settings in main.c
extern uint32_t	currentEpochTime;
extern uint8_t 	log_state, log_header_changed;
extern LogHeaderDef logHeader;

/*
 * Select the right panel to display on the LCD based on the user button pressed
 * It will also put the correct highlight selection as well as the dynamic data that is being
 * exchanged with the user
 */
void updateDisplay(uint8_t	button_state) {

	switch (paneNum) {
		case 0:							// Data Logger Main panel
			switch (button_state) {
				case BT0_DOWN:
					paneNum = 1;
					displayStaticPane(paneNum);
					break;
				case BT1_DOWN:

					break;
				case BT2_DOWN:			// Status
					paneNum = 2;
					displayStaticPane(paneNum);
					manageStatusPane();
					break;

				default:
					break;
			}
			break;
		case 1:						// Menu
			switch (button_state) {
				case BT0_DOWN:
					if (panels[paneNum].last_selection_index == 4) {
						panels[paneNum].last_selection_index = 1;
					} else {
						panels[paneNum].last_selection_index++;
					}
					displayStaticPane(paneNum);
					break;
				case BT1_DOWN:
					switch (panels[paneNum].last_selection_index) {
						case 1:
							paneNum=3;
							displayStaticPane(paneNum);
							// get current system date and time
							currentEpochTime = RTC_GetCounter();
							RTC_WaitForLastTask();
							epoch_to_time(currentEpochTime,&date_time);
							manageDateTimeInput(paneNum,1,&date_time,INIT); //display current date and time
							break;
						case 2:
							paneNum=4;
							displayStaticPane(paneNum);
							break;
						case 3:
							paneNum=5;
							displayStaticPane(paneNum);
							break;
						case 4:
							paneNum=6;
							displayStaticPane(paneNum);
							manageLCDOffPane(INIT);
							break;
						default:
							break;
					}
					break;
				case BT2_DOWN:
					paneNum=0;
					displayStaticPane(paneNum);
					break;

				default:
					break;
			}
			break;
		case 2:					// Status
			switch (button_state) {
				case BT0_DOWN:

					break;
				case BT1_DOWN:

					break;
				case BT2_DOWN:
					paneNum = 0;
					displayStaticPane(paneNum);
					break;

				default:
					break;
			}
			break;
		case 3:						// Date and Time
			switch (button_state) {
				case BT0_DOWN:
					manageDateTimeInput(paneNum,1,&date_time,BT0_DOWN);	// increment selected date and time field
					break;
				case BT1_DOWN:		// store the new date in time in our RTC
					currentEpochTime = time_to_epoch(&date_time);
					RTC_WaitForLastTask();
					RTC_SetCounter(currentEpochTime);
					// check if the new time falls within the sampling window or not
					if (currentEpochTime >= userSettings.startLogTime && currentEpochTime < userSettings.stopLogTime) {
						if (log_state == DISABLED) {	//Do not disturb the logging if it was already running
							log_state=ENABLED;
							RTC_SetAlarm(RTC_GetCounter());
							RTC_WaitForLastTask();
							RTC_ALR_Interrupt(ENABLE);
							RTC_WaitForLastTask();
							log_header_changed = TRUE;
							if (userSettings.log_update_mode == OVERWRITE) {
								// reset the EEPROM writing address
								userSettings.eepromWriteAddr=sizeof_userSettingsStruct();
							}
						}
					} else {
						log_state=DISABLED;
						RTC_ALR_Interrupt(DISABLE);
						storeUserSettings(0, &userSettings);	//Store latest eepromWriteAddr
					}
					paneNum=1;		// save date and time and go back to prev pane
					displayStaticPane(paneNum);
					break;
				case BT2_DOWN:
					manageDateTimeInput(paneNum,1,&date_time,BT2_DOWN);	// Tab to the next field in the same panel
					break;
				default:
					break;
			}
			break;
		case 4:						// Logging Management
			switch (button_state) {
				case BT0_DOWN:
					if (panels[paneNum].last_selection_index == 3) {
						panels[paneNum].last_selection_index = 1;
					} else {
						panels[paneNum].last_selection_index++;
					}
					displayStaticPane(paneNum);
					break;
				case BT1_DOWN:
					switch (panels[paneNum].last_selection_index) {
						case 1:
							paneNum=7;		//Log start/stop
							displayStaticPane(paneNum);
							epoch_to_time(userSettings.startLogTime,&date_time);
							manageDateTimeInput(paneNum,2,&date_time,INIT);		// display the start logging time stamp
							epoch_to_time(userSettings.stopLogTime,&date_time2);
							manageDateTimeInput(paneNum,4,&date_time2,INIT);	// display the stop  logging time stamp
							break;
						case 2:
							paneNum=8;		//Log Frequency
							displayStaticPane(paneNum);
							manageLogFreqPane(INIT);
							break;
						case 3:
							paneNum=9;		//New Log handling
							if (userSettings.log_update_mode== APPEND) {
								panels[paneNum].last_selection_index=1;
							} else {
								panels[paneNum].last_selection_index=2;
							}

							displayStaticPane(paneNum);
							break;
						default:
							break;
					}
					break;
				case BT2_DOWN:
					paneNum=1;
					displayStaticPane(paneNum);
					break;

				default:
					break;
			}
			break;
		case 5:					// PC Transfer
			switch (button_state) {
				case BT0_DOWN:			// Yes
					paneNum=10;
					displayStaticPane(paneNum);	// display empty pane
					manageSerialPane();			// A FSM to handle transmitting the EEPROM content
					break;
				case BT1_DOWN:

					break;
				case BT2_DOWN:		// Cancel
					paneNum=1;
					displayStaticPane(paneNum);
					break;

				default:
					break;
			}
			break;

		case 6:					// LCD options
			manageLCDOffPane(button_state);	// manage the LCD OFF time values
			break;

		case 7:						// start / stop logging
			switch (button_state) {
			case BT0_DOWN:
				if (panels[paneNum].last_selection_index == 2) {			// We are incrementing the start time
					manageDateTimeInput(paneNum,2,&date_time,BT0_DOWN);
				} else {
					manageDateTimeInput(paneNum,4,&date_time2,BT0_DOWN);	// We are incrementing the stop time
				}
				break;
			case BT1_DOWN:
				// store the date and time of recording start and stop
				date_time.tm_sec=0;
				date_time2.tm_sec=0;
				userSettings.startLogTime = time_to_epoch(&date_time);
				userSettings.stopLogTime = time_to_epoch(&date_time2);
				if (userSettings.startLogTime > userSettings.stopLogTime) {	// error
					// Display an error message
					break;					// do not store any information and stay in the same pane
				}

				currentEpochTime = RTC_GetCounter();

				if (currentEpochTime < userSettings.startLogTime) {
					// we did not reach the time to start logging
					log_header_changed = TRUE;	// We will need to store the logHeader later
					// Set the Alarm to wake up after x seconds from current time
					RTC_SetAlarm(userSettings.startLogTime - currentEpochTime);
					/* Wait until last write operation on RTC registers has finished */
					RTC_WaitForLastTask();
					RTC_ALR_Interrupt(ENABLE);
					log_state=DISABLED;		// Show it as stopped in the status pane.
				} else // current time between the start and stop time stamp, then start immediately to log
				if (currentEpochTime >= userSettings.startLogTime && currentEpochTime < userSettings.stopLogTime) {
					if (log_state == DISABLED) { // we were not logging already
						userSettings.startLogTime = RTC_GetCounter(); // record on eeprom current date and time
						log_header_changed = TRUE;	// We will need to store the logHeader later
						log_state=ENABLED;
						RTC_SetAlarm(RTC_GetCounter());
						RTC_WaitForLastTask();
						RTC_ALR_Interrupt(ENABLE);
						RTC_WaitForLastTask();
						if (userSettings.log_update_mode == OVERWRITE) {
							// reset the EEPROM writing address
							userSettings.eepromWriteAddr=sizeof_userSettingsStruct();
						}
					}
				} else {					// current time after the stop time, then disable logging
					log_state=DISABLED;
					RTC_ALR_Interrupt(DISABLE);
				}
				storeUserSettings(0, &userSettings);	// Store in EEPROM new Start/Stop time stamps
				paneNum=4;
				displayStaticPane(paneNum);
				break;

			case BT2_DOWN:
				if (panels[paneNum].last_selection_index == 2) {		// We are tabbing to next field
					if (selected_date_time_field == MINUTE) {			// If we were on the minutes tab then move
						panels[paneNum].last_selection_index = 4;		// to the stop time stamp fields
						LCD5110_set_XY(date_time_selection[4],2);		// Remove the selection from the minutes field of the start line
						LCD5110_Write_Dec(date_time.tm_min,NORMAL,2);
						manageDateTimeInput(paneNum,4,&date_time2,BT2_DOWN);
					} else {
						manageDateTimeInput(paneNum,2,&date_time,BT2_DOWN);
					}
				} else {
					if (selected_date_time_field == MINUTE) {
						panels[paneNum].last_selection_index = 2;
						LCD5110_set_XY(date_time_selection[4],4);		// Remove the selection from the minutes field of the stop line
						LCD5110_Write_Dec(date_time2.tm_min,NORMAL,2);
						manageDateTimeInput(paneNum,2,&date_time,BT2_DOWN);
					} else {
						manageDateTimeInput(paneNum,4,&date_time2,BT2_DOWN);
					}
				}
				break;
			default:
				break;
			}
			break;
		case 8:			// logging frequency
			switch (button_state) {
			case BT0_DOWN:	// increment frequency value or unit
				manageLogFreqPane(BT0_DOWN);
				break;
			case BT1_DOWN:		// store the user selection for frequency unit and value
				manageLogFreqPane(BT1_DOWN);
				paneNum=4;
				displayStaticPane(paneNum);
				break;
			case BT2_DOWN:
				manageLogFreqPane(BT2_DOWN);
				break;

			default:
				break;
			}
			break;

		case 9:			// How to handle a new Log
			switch (button_state) {
			case BT0_DOWN:
				if (panels[paneNum].last_selection_index == 2) {
					panels[paneNum].last_selection_index = 1;
				} else {
					panels[paneNum].last_selection_index++;
				}
				break;
			case BT1_DOWN: // How to handle the next Log
				switch (panels[paneNum].last_selection_index) {
					case 1:				// Save "Amend to prev Log" option
						paneNum=4;
						userSettings.log_update_mode= APPEND;
						break;
					case 2:				// Save "Log from Start" option
						paneNum=4;
						userSettings.log_update_mode= OVERWRITE;
						break;
					default:
						break;
				}
				storeUserSettings(0, &userSettings);	// Store in EEPROM new Start/Stop time stamps
				break;
			case BT2_DOWN:
				paneNum = 4;
				break;

			default:
				break;
			}
			displayStaticPane(paneNum);
			break;

		case 10:					// PC Transfer
			switch (button_state) {
				case BT0_DOWN:

					break;
				case BT1_DOWN:

					break;
				case BT2_DOWN:
					paneNum=5;
					break;

				default:
					break;
			}
			displayStaticPane(paneNum);
			break;

		case 11:				// Error message stop time smaller than start time
		case 12:				// Error message not enough storage to handle all the expected samples.
			switch (button_state) {
				case BT0_DOWN:

					break;
				case BT1_DOWN:

					break;
				case BT2_DOWN:
					paneNum=7;
					break;

				default:
					break;
			}
			displayStaticPane(paneNum);
			break;
		case 13:				// Error message reading sensor
			switch (button_state) {
				case BT0_DOWN:

					break;
				case BT1_DOWN:

					break;
				case BT2_DOWN:
					paneNum=prevPaneNum;
					break;

				default:
					break;
			}
			displayStaticPane(paneNum);
			break;
		default:
			break;
	}
}


void handleUserInterface(void){
	updateButtonState();
    if (processButtonState != BT_DONE) {	  // update LCD display based on key pressed
	  updateDisplay(processButtonState);
	  	  	  	  	  	  	  	  	  // pass the button state as it may change to BT_UP
	  	  	  	  	  	  	  	  	  // while we are processing the display
	  processButtonState = BT_DONE;
	}
}

/*
 * Parse the interrupt received. Waits for 5ms as debouncing then read the corresponding button pin. If same state as when the interrupt
 * was received, then valid key and update buttonState variable else, false.
 *
 * The logic below handles the debouncing for button pressing as well as button release.
 */
void updateButtonState(void){
	  uint16_t	gpioPin, tempISR_type;
	  uint32_t	extiLineNum;

	  Delay(5);						// Wait 5 ms for key debounce then test again.
	  	  	  	  	  	  	  	  	  // There is already HW debouncing

	  tempISR_type = ISR_type & (ISR_EXTI12 | ISR_EXTI13 | ISR_EXTI14 | ISR_EXTI15);

	  switch (tempISR_type) {
		case ISR_EXTI12:
			gpioPin=GPIO_Pin_12;
			extiLineNum=EXTI_Line12;
			ISR_type &= ~ISR_EXTI12; 		// Clear this ISR flag
			break;
		case ISR_EXTI13:
			gpioPin=GPIO_Pin_13;
			extiLineNum=EXTI_Line13;
			ISR_type &= ~ISR_EXTI13; 		// Clear this ISR flag
			break;
		case ISR_EXTI14:
			gpioPin=GPIO_Pin_14;
			extiLineNum=EXTI_Line14;
			ISR_type &= ~ISR_EXTI14; 		// Clear this ISR flag
			break;
		case ISR_EXTI15:
			gpioPin=GPIO_Pin_15;
			extiLineNum=EXTI_Line15;
			ISR_type &= ~ISR_EXTI15; 		// Clear this ISR flag
			break;
		default:							// Clear all buttons flags as multiple keys pressed
			ISR_type &= ~(ISR_EXTI12|ISR_EXTI13|ISR_EXTI14|ISR_EXTI15);
			break;
	}

									// Read user button status. It is active Low
	 if (buttonState != BT_UP) {
									 // pin high while it was supposed to be low
		 if (GPIO_ReadInputDataBit(GPIOB, gpioPin)) {
			 buttonState = BT_UP;	// Fake press
		} else {
			// Prepare to detect button_up action and debounce it
			configure_EXTI(extiLineNum,EXTI_Trigger_Rising);
		}
	  } else {
									  // pin high as it was supposed to be
		 if (GPIO_ReadInputDataBit(GPIOB, gpioPin)) {
			// Prepare to detect button_down action next time and debounce it
			configure_EXTI(extiLineNum,EXTI_Trigger_Falling);
		}
	  }
	 //very important, I was driven crazy without the below line
	 // before this call as the button bouncing was setting the bit while I was in delay mode
	  EXTI_ClearITPendingBit(extiLineNum);

	  EnableButton_IRQ(EXTI15_10_IRQn);	// Enable interrupt again
}

/*
 * This function takes the button pressed and follow a finite state machine structure
 * to manage the user interaction with the date and time panel.
 * It takes as input:
 *  - Panel Number
 * 	- The row on which the date and time will be displayed
 * 	- Pointer to a date&time structure to fill it with user selections
 * 	- which button the user has pressed (either Next or Increment). INIT is to initialize with default values when first called
 *
 */
void manageDateTimeInput(uint8_t paneNum, uint8_t LCD_row, epochTimeTypeDef *date_time, uint8_t state) {

	switch (state) {
		case INIT:			// called first time, then initialize and display current
			LCD5110_set_XY(date_time_selection[0],LCD_row);	//day location on LCD
			if (paneNum == 9 && LCD_row == 4) {	// We are in the start/stop panel and displaying the stop time stamp
				LCD5110_Write_Dec(date_time->tm_mday,NORMAL,2);
			} else {
				LCD5110_Write_Dec(date_time->tm_mday,REVERSE,2);
			}
			LCD5110_set_XY(date_time_selection[1],LCD_row);	//month location on LCD
			LCD5110_Write_Dec(date_time->tm_mon+1, NORMAL,2);
			LCD5110_set_XY(date_time_selection[2],LCD_row);	//year location on LCD
			LCD5110_Write_Dec(1900+date_time->tm_year-2000, NORMAL,2);
			LCD5110_set_XY(date_time_selection[3],LCD_row);	//hour location on LCD
			LCD5110_Write_Dec(date_time->tm_hour, NORMAL,2);
			LCD5110_set_XY(date_time_selection[4],LCD_row);	//min location on LCD
			LCD5110_Write_Dec(date_time->tm_min, NORMAL,2);
			selected_date_time_field = DAY;
			break;

		case BT0_DOWN:	// Increment field value
			switch (selected_date_time_field) {
				case DAY:
					if (date_time->tm_mday == 31) {
						date_time->tm_mday = 1;
					} else {
						date_time->tm_mday++;
					}
					LCD5110_set_XY(date_time_selection[0],LCD_row);	//day location on LCD
					LCD5110_Write_Dec(date_time->tm_mday, REVERSE,2);
					break;
				case MONTH:
					if (date_time->tm_mon == 11) {
						date_time->tm_mon = 0;
					} else {
						date_time->tm_mon++;
					}
					LCD5110_set_XY(date_time_selection[1],LCD_row);	//month location on LCD
					LCD5110_Write_Dec(date_time->tm_mon+1, REVERSE,2);
					break;
				case YEAR:
					if (date_time->tm_year == 120) {	//Till year 2020
						date_time->tm_year = 113;		// year 2013
					} else {
						date_time->tm_year++;
					}
					LCD5110_set_XY(date_time_selection[2],LCD_row);	//month location on LCD
					LCD5110_Write_Dec(1900+date_time->tm_year-2000, REVERSE,2);
					break;
				case HOUR:
					if (date_time->tm_hour == 23) {
						date_time->tm_hour = 0;
					} else {
						date_time->tm_hour++;
					}
					LCD5110_set_XY(date_time_selection[3],LCD_row);	//month location on LCD
					LCD5110_Write_Dec(date_time->tm_hour, REVERSE,2);
					break;
				case MINUTE:
					if (date_time->tm_min == 59) {
						date_time->tm_min = 0;
					} else {
						date_time->tm_min++;
					}
					LCD5110_set_XY(date_time_selection[4],LCD_row);	//month location on LCD
					LCD5110_Write_Dec(date_time->tm_min, REVERSE,2);
					break;
				default:
					break;
			}
			break;

		case BT2_DOWN:	// tab to next field
			switch (selected_date_time_field) {
				case DAY:
					// Turn off previous selection
					LCD5110_set_XY(date_time_selection[0],LCD_row);	//day location on LCD
					LCD5110_Write_Dec(date_time->tm_mday, NORMAL,2);
					// Turn on new selection
					selected_date_time_field = MONTH;
					LCD5110_set_XY(date_time_selection[1],LCD_row);	//month location on LCD
					LCD5110_Write_Dec(date_time->tm_mon+1, REVERSE,2);
					break;
				case MONTH:
					LCD5110_set_XY(date_time_selection[1],LCD_row);	//month location on LCD
					LCD5110_Write_Dec(date_time->tm_mon+1, NORMAL,2);
					selected_date_time_field = YEAR;
					LCD5110_set_XY(date_time_selection[2],LCD_row);	//year location on LCD
					LCD5110_Write_Dec(1900+date_time->tm_year-2000, REVERSE,2);
					break;
				case YEAR:
					LCD5110_set_XY(date_time_selection[2],LCD_row);	//year location on LCD
					LCD5110_Write_Dec(1900+date_time->tm_year-2000, NORMAL,2);
					selected_date_time_field = HOUR;
					LCD5110_set_XY(date_time_selection[3],LCD_row);	//hour location on LCD
					LCD5110_Write_Dec(date_time->tm_hour, REVERSE,2);
					break;
				case HOUR:
					LCD5110_set_XY(date_time_selection[3],LCD_row);	//hour location on LCD
					LCD5110_Write_Dec(date_time->tm_hour, NORMAL,2);
					selected_date_time_field = MINUTE;
					LCD5110_set_XY(date_time_selection[4],LCD_row);	//minute location on LCD
					LCD5110_Write_Dec(date_time->tm_min, REVERSE,2);
					break;
				case MINUTE:
					LCD5110_set_XY(date_time_selection[4],LCD_row);	//month location on LCD
					LCD5110_Write_Dec(date_time->tm_min, NORMAL,2);
					selected_date_time_field = DAY;
					LCD5110_set_XY(date_time_selection[0],LCD_row);	//day location on LCD
					LCD5110_Write_Dec(date_time->tm_mday, REVERSE,2);
					break;
				default:
					break;
			}
	}
}

void manageLogFreqPane(uint8_t state){

	switch (state) {
		case INIT:										// called first time, then initialize and display current
														// log frequency and unit of measurement
			tempFreqVal = userSettings.freq_val;		// We use a temp variable as the user may leave the panel without saving
			tempFreqType = userSettings.freq_type;		// We use a temp variable as the user may leave the panel without saving
			LCD5110_set_XY(4,2);
			LCD5110_Write_Dec(tempFreqVal,REVERSE,2);	// display the value
			LCD5110_set_XY(7,2);
														// display the unit of measurement
			LCD5110_write_string(freq_unit_abrv[tempFreqType]);
			freq_selection = FREQ_VALUE;				// We will start by changing the value.
			break;

		case BT0_DOWN:	// Increment Field Value
			switch (freq_selection) {
				case FREQ_VALUE:
					switch (tempFreqType) {
						case FREQ_UNIT_MINUTES:
							if (tempFreqVal == 60) {
								tempFreqVal = 1;
							} else {
								tempFreqVal++;
							}
							break;
						case FREQ_UNIT_HOURS:
							if (tempFreqVal == MAX_HOURS_FREQ) {
								tempFreqVal = 1;
							} else {
								tempFreqVal++;
							}
							break;
						case FREQ_UNIT_DAYS:
							if (tempFreqVal == MAX_DAYS_FREQ) {
								tempFreqVal = 1;
							} else {
								tempFreqVal++;
							}
							break;

						default:
							break;
					}
					LCD5110_set_XY(4,2);
					LCD5110_Write_Dec(tempFreqVal,REVERSE,2);	// display the value
					break;

				case FREQ_UNIT:									// Increment the frequency unit but update the value if it goes outside limit
					switch (tempFreqType) {
						case FREQ_UNIT_MINUTES:
							tempFreqType = FREQ_UNIT_HOURS;
							if (tempFreqVal >= MAX_HOURS_FREQ) {
								tempFreqVal = 1;
							}
							break;
						case FREQ_UNIT_HOURS:
							tempFreqType = FREQ_UNIT_DAYS;
							if (tempFreqVal >= MAX_DAYS_FREQ) {
								tempFreqVal = 1;
							}
							break;
						case FREQ_UNIT_DAYS:
							tempFreqType = FREQ_UNIT_MINUTES;
							if (tempFreqVal >= 60) {
								tempFreqVal = 1;
							}
							break;
						default:
							break;
					}
					LCD5110_set_XY(4,2);
					LCD5110_Write_Dec(tempFreqVal,NORMAL,2);	// display the value
					LCD5110_set_XY(7,2);
					LCD5110_write_string("     ");				// clear before writing new frequency type
					LCD5110_set_XY(7,2);
					LCD5110_write_string_rev(freq_unit_abrv[tempFreqType]);			// display the unit
				break;
				default:
					break;
			}

			break;

		case BT1_DOWN:	// Save logging frequency
			userSettings.freq_type = tempFreqType;
			userSettings.freq_val = tempFreqVal;
			RTC_Alarm_Count=Calc_RTC_Alarm_Count(tempFreqType,tempFreqVal);

			log_header_changed = TRUE;	// We will need to store the logHeader later
			userSettings.startLogTime = RTC_GetCounter(); // record on eeprom current date and time
			storeUserSettings(0, &userSettings);	// Store in EEPROM new sampling frequency
			paneNum = 4;
			displayStaticPane(4);
			break;

			case BT2_DOWN:	// tab to next field
				switch (freq_selection) {
					case FREQ_UNIT:
						freq_selection = FREQ_VALUE;
						LCD5110_set_XY(7,2);
						LCD5110_write_string(freq_unit_abrv[tempFreqType]);			// display the type
						LCD5110_set_XY(4,2);
						LCD5110_Write_Dec(tempFreqVal,REVERSE,2);	// display the value
						break;
					case FREQ_VALUE:
						freq_selection = FREQ_UNIT;
						LCD5110_set_XY(4,2);
						LCD5110_Write_Dec(tempFreqVal,NORMAL,2);	// display the value
						LCD5110_set_XY(7,2);
						LCD5110_write_string_rev(freq_unit_abrv[tempFreqType]);	// display the value
						break;

					default:
						break;
				}
				break;
			default:
				break;
	}
}

void manageLCDOffPane(uint8_t state){

}

void manageStatusPane(void) {
	uint16_t samplesLeft;
	samplesLeft = (EEPROM_SIZE - userSettings.eepromWriteAddr)/sizeof_dataRecStruct();
	LCD5110_set_XY(4,1);
	LCD5110_Write_Dec(samplesLeft,NORMAL,0);
	LCD5110_set_XY(2,2);
	if (log_state == ENABLED) {
		LCD5110_write_string(" Running..");
	} else {
		LCD5110_write_string(" Stopped..");
	}
	LCD5110_set_XY(3,4);			// display the sampling frequency
									// "   xx xxxx    "
	LCD5110_Write_Dec(userSettings.freq_val,NORMAL,2);
	LCD5110_set_XY(6,4);
	LCD5110_write_string(freq_unit_abrv[userSettings.freq_type]);
}

/*
 * A FSM to handle transmitting the EEPROM content.
 * In the INIT State, it will send the Heading. If successful, it will change state to SEND_LOG_HEADER
 * And so on.
 * It will be called in the main loop whenever the TX buffer of the USART is empty
 * If succeeds in sending header, then change panel text to "Sending.." else display "
 */
void manageSerialPane(void){

	LCD5110_set_XY(0,2);		// display initially "Waiting..."
	LCD5110_write_string("  Waiting...  ");
	serial_dump_eeprom();	// initialize and send the headings string
}
